﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Facebook;

namespace FeedBack {
    public class FeedProcessor {

        public event EventHandler<StoryProcessedEventArgs> StoryProcessed;
        public event EventHandler Completed;
        public event EventHandler<VideoInProgressUpdatedEventArgs> VideoInProgressUpdated;

        private DateTime threshold;
        private StoryProcessor storyProcessor = new StoryProcessor();
        private FacebookClient fb;
        
        public string CompleteStatus { get; private set; }

        public FeedProcessor(FacebookClient fb, DateTime threshold) {
            this.fb = fb;
            this.threshold = threshold;
        } 

        public void Process() {
            ProcessUser("me", "home");
            ProcessUser("me", "feed");
            OnCompleted();
        }

        public void ProcessUsers(IEnumerable<string> ids) {
            HashSet<NetworkStoryParser> parsers = new HashSet<NetworkStoryParser>();
            foreach (var id in ids.Where(o => !string.IsNullOrWhiteSpace(o))) {
                var userId = id;
                if (id.StartsWith("http://") || id.StartsWith("https://")) {
                    try {
                        Uri uri = new Uri(id);
                        var path = uri.PathAndQuery;
                        if (path.Contains("?")) {
                            path = path.Substring(0, path.IndexOf('?'));
                        }
                        var parts = path.Split(new char[]{'/'}, StringSplitOptions.RemoveEmptyEntries);
                        if (parts[0] == "pages") {
                            userId = parts[2];
                        }
                        else {
                            userId = parts[0];
                        }
                    }
                    catch {
                        continue;
                    }
                }

                System.Diagnostics.Debug.WriteLine(userId);
                try {
                    var result = fb.Get(userId) as JsonObject;
                    if (result.Get<string>("id") != null) {
                        NetworkStoryParser parser = CreateNetworkStoryParser(string.Format("{0}/{1}", userId, "feed"));
                        parsers.Add(parser);
                    }
                }
                catch { }
                Thread.Sleep(1000);
            }

            CompositStoryParser compositStoryParser = new CompositStoryParser(parsers);
            ProcessFeed(compositStoryParser);
            OnCompleted();
        }

        private void ProcessUser(string userId, string streamName = "feed") {
            NetworkStoryParser parser = CreateNetworkStoryParser(string.Format("{0}/{1}", userId, streamName));
            ProcessFeed(parser);
        }

        public void Process(string initPath, int i) {
            NetworkStoryParser parser = CreateNetworkStoryParser(initPath, i);
            ProcessFeed(parser);
            OnCompleted();
        }

        private NetworkStoryParser CreateNetworkStoryParser(string initPath, int i = 0) {
            if (!initPath.Contains("limit=")) {
                if (initPath.Contains("?")) {
                    initPath = initPath + "&limit=" + Configuration.Limit;
                }
                else {
                    initPath = initPath + "?limit=" + Configuration.Limit;
                }
            }

            NetworkStoryParser parser = new NetworkStoryParser(fb, initPath, threshold, i);
            return parser;
        }

        public void ProcessFileFeed(IEnumerable<string> files) {

            FileStoryParser parser = new FileStoryParser(files, fb.DeserializeJson);
            ProcessFeed(parser);
            OnCompleted();
        }

        private void ProcessFeed(IStoryParser parser) {
            if (VideoInProgressUpdated != null) {
                storyProcessor.VideoInProgressUpdated += VideoInProgressUpdated;
            }

            PrepareWorkingFolder();
            foreach (JsonObject story in parser.GetStories()) {
                storyProcessor.Process(story);
                if (StoryProcessed != null) {
                    StoryProcessed(this, new StoryProcessedEventArgs { Story = story });
                }

                for (; storyProcessor.StoryInProgress > Configuration.ConcurrentDownload; ) {
                    System.Threading.Thread.Sleep(1000);
                }
            }
            CompleteStatus = "All feed entries processed";
        }

        private static void PrepareWorkingFolder() {
            if (Directory.Exists(Configuration.InProgressFolder)) {
                foreach (var file in Directory.GetFiles(Configuration.InProgressFolder)) {
                    try {
                        File.Delete(file);
                    }
                    catch { }
                }
            }
            else {
                Configuration.InProgressFolder.EnsureDirectory();
            }
        }

        private void OnCompleted() {
            if (Completed != null) {
                Completed(this, new EventArgs());
            }
        }
    }
}
